﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Clandestine.Conversations;
using System.IO;
using JibberJabber.Controls;
using JibberJabber.PartDesigners;

namespace JibberJabber
{
    public partial class frmMain : Form
    {
        PartDesigner currPd = null;

        public frmMain()
        {
            InitializeComponent();
        }

        public void UpdateTree()
        {
            tv.Nodes.Clear();

            TreeNode rootNode = new TreeNode("Root Node");
            rootNode.Tag = Program.Root;
            tv.Nodes.Add(rootNode);
            Program.Root.AssociatedNode = rootNode;
            addNode(Program.Root, rootNode, true);
            tv.ExpandAll();

            // can't see easy non-hacky solution
            if (currPd != null)
                tv.SelectedNode = currPd.AssociatedNode;
        }

        private void addNode(PartDesigner pd, TreeNode parentNode, bool childrenOnly)
        {
            TreeNode tn = parentNode;

            if (!childrenOnly)
            {
                tn = new TreeNode(pd.ToString());
                pd.AssociatedNode = tn;
                tn.Tag = pd;
                parentNode.Nodes.Add(tn);
            }

            lock (pd.Children)
                if (pd.Children.Count > 0)
                {
                    foreach (PartDesigner cpd in pd.Children)
                        addNode(cpd, tn, false);
                }
                else if (pd.AllowedChildren.Length > 0)
                    tn.Nodes.Add("(add children here)");
        }


        private void setNoneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.Preview.Background.Clear();
        }

        private void setLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (ofdLevel.ShowDialog() == DialogResult.OK)
                    Program.Preview.Background.SetLevel(ofdLevel.FileName);
            }
            catch (Exception exc)
            {
                MessageBox.Show("An Exception was thrown when trying to load the Level.\n\n"
                    + exc.ToString(), "Error", MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void setTextureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (ofdBitmap.ShowDialog() == DialogResult.OK)
                    Program.Preview.Background.SetBitmap(ofdBitmap.FileName);
            }
            catch (Exception exc)
            {
                MessageBox.Show("An Exception was thrown when trying to load the texture.\n\n"
                    + exc.ToString(), "Error", MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void panCameraToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new frmPan().Show();
        }

        private void fromTheTopToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.Preview.Pause();
            Program.Preview.ClearFuckingEverything();
            Program.Preview.ChangeConversation(
                new Conversation(SaveEverything.SaveToXmlTextReader()));
            Program.Preview.Resume();
        }

        private void tv_AfterSelect(object sender, TreeNodeMouseClickEventArgs e)
        {
            addmenu.DropDownItems.Clear();
            addSubnodeToolStripMenuItem.DropDownItems.Clear();

            // Menu items can only belong to one parent menu item :/
            // Otherwise, the add silently fails.
            // Hence the doing absolutely everything twice here...

            if (e.Node.Tag != null)
            {
                PartDesigner pd = ((PartDesigner)e.Node.Tag);
                // Hide current form (if any), show new form.
                changePartDesigner(pd);

                // Update 'Add' context menu.
                Type[] possibleSubnodes = pd.AllowedChildren;
                if (possibleSubnodes.Length == 0)
                {
                    addmenu.Text = "Can't add!";
                    addSubnodeToolStripMenuItem.Text = "Can't add!";
                }
                else
                {
                    addmenu.Text = "Add";
                    addSubnodeToolStripMenuItem.Text = "Add Sub-Node";
                    foreach (Type t in possibleSubnodes)
                    {
                        addmenu.DropDownItems.Add(new AddChildMenuItem(pd, t));
                        addSubnodeToolStripMenuItem.DropDownItems.Add(new AddChildMenuItem(pd, t));
                    }
                }
            }
            else
            {
                addmenu.Text = "Can't add!";
                addSubnodeToolStripMenuItem.Text = "Can't add!";
            }

            tv.SelectedNode = e.Node;
        }

        private void changePartDesigner(PartDesigner pdNew)
        {
            if (currPd != null)
                currPd.Hide();
            currPd = pdNew;
            currPd.Show();
            currPd.Location = new Point(this.Location.X + this.Width,
                this.Location.Y);
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tv.SelectedNode != null)
            {
                if (tv.SelectedNode.Tag != null)
                {
                    PartDesigner pd = ((PartDesigner)tv.SelectedNode.Tag);
                    TreeNode parentNode = tv.SelectedNode.Parent;

                    if (parentNode.Tag != null)
                    {
                        if (pd is RootNodeDesigner || pd is SpeakersNodeDesigner)
                            MessageBox.Show("You can't delete this node.");
                        else
                        {
                            if (MessageBox.Show("Are you sure you want to delete node '" + pd.ToString() + "'?",
                                "Confirm Deletion", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
                                == DialogResult.OK)
                            {
                                // select parent
                                tv_AfterSelect(null, new TreeNodeMouseClickEventArgs(parentNode, MouseButtons.Left, 1, 0, 0));
                                // Delete it!
                                PartDesigner pdParent = ((PartDesigner)parentNode.Tag);
                                Program.RemoveChildPartDesigner(pdParent, pd);
                            }
                        }
                        return;
                    }
                }
            }

            MessageBox.Show("No node is selected.", "Delete",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// Throws up a Yes/No/Cancel dialog. If Cancel is pressed, false is returned.
        /// </summary>
        /// <returns>Bool representing whether to continue the original action.</returns>
        private bool saveIfUserWants()
        {
            switch (MessageBox.Show("Save changes to " + Program.Filename + "?",
                "Save", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
            {
                case DialogResult.Yes:
                    saveToolStripMenuItem_Click(null, null);
                    return true;

                case DialogResult.No:
                    return true;

                case DialogResult.Cancel:
                    return false;
            }
            return false;
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveIfUserWants())
                Program.Reset();
        }

        public void DeselectCurrPd()
        {
            if (currPd != null)
            {
                currPd.Hide();
                currPd = null;
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!Program.SavedEver)
                saveAsToolStripMenuItem_Click(sender, e);
            else
                File.WriteAllText(Program.Filename, SaveEverything.Save());
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (sfdDialogue.ShowDialog() == DialogResult.OK)
            {
                Program.SavedEver = true;
                Program.Filename = sfdDialogue.FileName;
                File.WriteAllText(Program.Filename, SaveEverything.Save());
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("TODO, pending loading code :(",
                "TODO", MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;

            if (!saveIfUserWants())
                return;

            if (ofdDialogue.ShowDialog() == DialogResult.OK)
            {
                Program.Reset();
                Program.SavedEver = true;
                Program.Filename = ofdDialogue.FileName;

                // LOADING CODE GOES HERE!!!
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // FormClosing will handle it.
            this.Close();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!saveIfUserWants())
                e.Cancel = true;
        }
    }
}
